/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.druid.msq.exec;

import org.apache.druid.msq.counters.CounterSnapshotsTree;
import org.apache.druid.msq.indexing.error.MSQErrorReport;
import org.apache.druid.msq.kernel.StageDefinition;
import org.apache.druid.msq.kernel.StageId;
import org.apache.druid.msq.kernel.WorkOrder;
import org.apache.druid.msq.statistics.PartialKeyStatisticsInformation;

import javax.annotation.Nullable;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;

/**
 * Client for the multi-stage query controller. Used by a {@link Worker}. Each instance is specific to a single query,
 * meaning it communicates with a single controller.
 */
public interface ControllerClient extends Closeable
{
  /**
   * Client side method to update the controller with partial key statistics information for a particular stage
   * and worker. The controller collates all the information for a stage to fetch key statistics from workers.
   *
   * Only used when {@link StageDefinition#mustGatherResultKeyStatistics()}.
   */
  void postPartialKeyStatistics(
      StageId stageId,
      int workerNumber,
      PartialKeyStatisticsInformation partialKeyStatisticsInformation
  ) throws IOException;

  /**
   * Client side method to tell the controller that a particular stage and worker is done reading its input.
   *
   * The main purpose of this call is to let the controller know when it can stop running the input stage. This helps
   * execution roll smoothly from stage to stage during pipelined execution. For backwards-compatibility reasons
   * (this is a newer method, only really useful when pipelining), this call should be skipped if the query is not
   * pipelining stages.
   *
   * Only used when {@link StageDefinition#doesSortDuringShuffle()} and *not*
   * {@link StageDefinition#mustGatherResultKeyStatistics()}. When the stage gathers result key statistics, workers
   * call {@link #postPartialKeyStatistics(StageId, int, PartialKeyStatisticsInformation)} instead, which has the same
   * effect of telling the controller that the worker is done reading its input.
   */
  void postDoneReadingInput(StageId stageId, int workerNumber) throws IOException;

  /**
   * Client-side method to update the controller with counters for a particular stage and worker. The controller uses
   * this to compile live reports, track warnings generated etc.
   */
  void postCounters(String workerId, CounterSnapshotsTree snapshotsTree) throws IOException;

  /**
   * Client side method to update the controller with the result object for a particular stage and worker. This also
   * informs the controller that the computation for that particular stage has been done by the worker.
   */
  void postResultsComplete(
      StageId stageId,
      int workerNumber,
      @Nullable Object resultObject
  ) throws IOException;

  /**
   * Client side method to inform the controller that the error has occured in the given worker.
   */
  void postWorkerError(
      String workerId,
      MSQErrorReport errorWrapper
  ) throws IOException;

  /**
   * Client side method to inform the controller about the warnings generated by the given worker.
   */
  void postWorkerWarning(List<MSQErrorReport> MSQErrorReports) throws IOException;

  /**
   * Client side method for retrieving the list of worker IDs from the controller. These IDs can be passed to
   * {@link WorkerClient} methods to communicate with other workers. Not necessary when the {@link WorkOrder} has
   * {@link WorkOrder#getWorkerIds()} set.
   *
   * @see Controller#getWorkerIds() for the controller side
   */
  List<String> getWorkerIds() throws IOException;

  /**
   * Close this client. Idempotent.
   */
  @Override
  void close();
}
